<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.0 / SVN信息: $Id: class.JCAT_RunTime.php 1594 2009-03-31 11:29:38Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/
namespace JCAT ;


/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
class RunTime
{
	const PHPHANDLE_ERROR = 'error' ;
	const PHPHANDLE_SHUTDOWN = 'shutdown' ;
	
	
	//// PHP Shutdown 事件 /////////////////////////////////////////////////////////////////////////////
	
	/**
	 * 注册一个 在 PHP执行结束 被调用的 收尾函数
	 *
	 * @access	public
	 * @param	$Callback
	 * @static
	 * @return	void
	 */
	static public function RegisterShutdownFunction($Callback)
	{
		self::RegisterPHPRuntimeHandle( $Callback, self::PHPHANDLE_SHUTDOWN ) ;
	}
	
	/**
	 * 移除一个 在 PHP执行结束 被调用的 收尾函数
	 *
	 * @access	public
	 * @param	$Callback
	 * @static
	 * @return	void
	 */
	static public function UnregisterShutdownFunction($Callback)
	{
		self::UnregisterPHPRuntimeHandle( $Callback, self::PHPHANDLE_SHUTDOWN ) ;
	}
	
	/**
	 * 检查 是否为 PHP执行结束时被调用的 收尾函数
	 *
	 * @access	public
	 * @param	$Callback
	 * @static
	 * @return	bool
	 */
	static public function IsShutdownFunction($Callback)
	{
		self::IsPHPRuntimeHandle( $Callback, self::PHPHANDLE_SHUTDOWN ) ;		
	}

	/**
	 * 响应 PHP执行结束事件 的方法
	 *
	 * @access	public
	 * @static
	 * @return	void
	 */
	static public function OnPHPShutdown()
	{		
		self::OnPHPRuntimeEvent(self::PHPHANDLE_SHUTDOWN) ;
	}
	
	/**
	 * 退出钩子函数：打印程序退出前产生的错误信息
	 *
	 * @access	public
	 * @static
	 * @return	void
	 */
	static public function PrintErrorBeforeShutdown()
	{
		$arrError = error_get_last() ;
		
		// 清除 ob 的影响
		$arrHandlers = ob_list_handlers() ;
		foreach ($arrHandlers as $Handler)
		{
			ob_end_flush() ;
		}
		
		if( $arrError!==null )
		{
			if( !($arrError['type']&E_WARNING) and !($arrError['type']&E_NOTICE) and !($arrError['type']&E_STRICT) )
			{
				$sOut = "Message: [{$arrError['type']}]{$arrError['message']}
File: {$arrError['file']}
Line: {$arrError['line']}" ;

				GlobalFunc::FormatOut($sOut) ;
			}
		}
	}

	//// PHP 错误事件 //////////////////////////////////////////////////////////////////////////////////

	/**
	 * 注册一个 在 PHP执行结束 被调用的 收尾函数
	 *
	 * @access	public
	 * @param	$Callback				callback
	 * @param	$nErrorType=E_ALL		int
	 * @static
	 * @return	void
	 */
	static public function RegisterErrorFunction($Callback,$nErrorType=E_ALL)
	{
		self::RegisterPHPRuntimeHandle( $Callback, self::PHPHANDLE_ERROR.':'.strval($nErrorType) ) ;
	}
	
	/**
	 * 移除一个 在 PHP执行结束 被调用的 收尾函数
	 *
	 * @access	public
	 * @param	$Callback				callback
	 * @param	$nErrorType=E_ALL		int
	 * @static
	 * @return	void
	 */
	static public function UnregisterErrorFunction($Callback,$nErrorType=E_ALL)
	{
		self::UnregisterPHPRuntimeHandle( $Callback, self::PHPHANDLE_ERROR.':'.strval($nErrorType) ) ;
	}
	
	/**
	 * 检查 是否为 PHP执行结束时被调用的 收尾函数
	 *
	 * @access	public
	 * @param	$Callback				callback
	 * @param	$nErrorType=E_ALL		int
	 * @static
	 * @return	bool
	 */
	static public function IsErrorFunction($Callback,$nErrorType=E_ALL)
	{
		self::IsPHPRuntimeHandle( $Callback, self::PHPHANDLE_ERROR.':'.strval($nErrorType) ) ;		
	}

	/**
	 * 响应 PHP错误事件 的方法
	 *
	 * @access	public
	 * @static
	 * @return	void
	 */
	static public function OnPHPError($nErrorNo,$sErrStr,$sErrFile,$nErrLine)
	{
		foreach (self::$arrPHPRuntimeHandles as $sHandleKey=>$arrFunctions)
		{
			$arrHandleKeyEles = explode(':',$sHandleKey) ;
			if( count($arrHandleKeyEles)!=2 or $arrHandleKeyEles[0]!==self::PHPHANDLE_ERROR )
			{
				continue ;
			}
			
			// 比较 错误类型
			$nHandleFlag = intval($arrHandleKeyEles[1]) ;
			if( $nHandleFlag&$nErrorNo )
			{
				self::OnPHPRuntimeEvent($sHandleKey,array($nErrorNo,$sErrStr,$sErrFile,$nErrLine)) ;
			}
		}
		
		// 继续执行 PHP 内置错误处理过程
		return false ;
	}

	
	
	/**
	 * 注册一个 PHP运行时事件 处理函数
	 *
	 * @access	public
	 * @param	$Callback
	 * @static
	 * @return	void
	 */
	static public function RegisterPHPRuntimeHandle($Callback,$sHandle)
	{
		if( self::FindPHPRuntimeHandle($Callback,$sHandle)===null )
		{
			self::$arrPHPRuntimeHandles[$sHandle][] = $Callback ;
		}
	}
	
	/**
	 * 移除一个 PHP运行时事件 处理函数
	 *
	 * @access	public
	 * @param	$Callback
	 * @static
	 * @return	void
	 */
	static public function UnregisterPHPRuntimeHandle($Callback,$sHandle)
	{
		$nIdx = self::FindPHPRuntimeHandle($Callback,$sHandle) ;
		if( $nIdx!==null )
		{
			unset(self::$arrPHPRuntimeHandles[$sHandle][$nIdx]) ;
		}
	}
	
	/**
	 * 查找一个 PHP运行时事件 处理函数
	 *
	 * @access	public
	 * @param	$Callback
	 * @static
	 * @return	bool
	 */
	static public function IsPHPRuntimeHandle($Callback,$sHandle)
	{
		return (self::FindPHPRuntimeHandle($Callback,$sHandle)!==null) ;
	}
	
	/**
	 * 查找一个 PHP运行时事件 处理函数
	 *
	 * @access	private
	 * @param	$Callback
	 * @static
	 * @return	int
	 */
	static private function FindPHPRuntimeHandle($Callback,$sHandle)
	{
		if( isset(self::$arrPHPRuntimeHandles[$sHandle]) )
		{
			foreach (self::$arrPHPRuntimeHandles[$sHandle] as $nIdx=>$Function)
			{
				if( GlobalFunc::IsSameCallback($Callback,$Function) )
				{
					return $nIdx ;
				}
			}
		}
		return null ;
	}

	/**
	 * 响应 PHP运行时事件 的方法
	 *
	 * @access	public
	 * @static
	 * @return	void
	 */
	static public function OnPHPRuntimeEvent($sHandle,$arrArgs=array())
	{
		if( isset(self::$arrPHPRuntimeHandles[$sHandle]) )
		{
			foreach (self::$arrPHPRuntimeHandles[$sHandle] as $Function)
			{
				call_user_func_array($Function,$arrArgs) ;
			}
		}
	}
	
		
	/**
	 * 所有注册的 在 PHP执行结束 被调用的 收尾函数
	 * 
	 * @access	private
	 * @static
	 * @var		array
	 */
	static private $arrPHPRuntimeHandles = array() ;
	
	
	
}

?>